#ifndef frm_control_TPanel_H
#define frm_control_TPanel_H

#include "svl_TValue.h"
#include "svl_TEvents.h"
#include "frm_geometry.h"
#include "frm_filler.h"
#include "frm_cursor.h"
#include "frm_TStyle.h"
#include "grf_TWindow.h"

namespace frm { namespace control {

///////////////////////////////////////////////////////////////////////////////
struct TPanel;
struct TWindow;
struct TTable;
///////////////////////////////////////////////////////////////////////////////

struct TPanelPaint
{
  TPanelPaint(TWindow &Window);
  //
  void Begin ();
  void Insert(TPanel *P);
  void End();
  void EndAll() { count = 0; End();}
  void Cancel();
  //
  void Invalidate(TPanel *P);

private:
  void destructor(TPanel *P);
  TPanel &Get(int N);
  //
  svl_Except;
  TWindow &window;
  int count; 
  svl::TArray a;
  friend TPanel;
};

////////////////////////////////////////////////////////////////////////////////

struct TPanelFocus
{
  grf::TCaret Caret;
  //
  TPanelFocus(TWindow &Window);
  //
  void SetPos     (int V) { pos = V; if (pos < 0) { pos = 0; } }
  void SetDeltaPos(int V) { SetPos(pos + V); }
  int  GetPos() { return pos;}
  int  GetX  () { return caretX;}
  //
  void SetEnterByPos(TPanel *V,TGeometryRect &GRect,int Pos);
  void SetEnterByX  (TPanel *V,TGeometryRect &GRect,int X);
  //
  void Exit();
  //
  TPanel *GetEnter() { return enter;}
  //
  void FixCaretX()    { caretX = Caret.RClient.Left;}
  void ShowCaret()    { Caret.Show(); }
  void HideCaret()    { Caret.Hide(); }
  void DestroyCaret() { Caret.Destroy(); }
  //
  bool IsEntered(TPanel *V);

private:
  bool SetEnter(TPanel *V,TGeometryRect &GRect);
  void destructor(TPanel *P);
  //
  TPanel *enter;
  int pos,caretX;
  TWindow &window;
  friend TPanel;
};

////////////////////////////////////////////////////////////////////////////////

struct TPanelSelect
{
  TPanelSelect(TPanel &Owner);
  //
  void    SetEnter(TPanel *V);
  TPanel *GetEnter() { return enter;}
  //
  void Exit() { SetEnter(NULL);}
  //
  bool IsEntered(TPanel *V);

private:
  void destructor(TPanel *V);
  //
  TPanel *enter;
  TPanel &owner;
  friend TPanel;
public:
  int sel_min, sel_max, sel_beg, sel_end;
  bool select, selecting;
};

////////////////////////////////////////////////////////////////////////////////

struct TPanelMouse
{
  TPanelMouse(TWindow &Window) : window(Window) { capture = enter = NULL;}
  //
  void    SetCapture(TPanel *V);
  TPanel *GetCapture() { return capture;}
  //
  void    SetEnter(TPanel *V);
  TPanel *GetEnter() { return enter;}

private:
  void destructor(TPanel *Panel);
  //
  TPanel *capture,*enter;
  TWindow &window;
  friend TPanel;
};

///////////////////////////////////////////////////////////////////////////////

struct TPanelStack
{
  TPanelStack() { count = 0;}
  //
  void Push(TPanel *C);
  bool Pop (TPanel *&C);

private:
  svl_Except;
  struct TItem { TPanel *C;} items[201];
  int count;
};

////////////////////////////////////////////////////////////////////////////////

struct TMergeSplit
{
  TPanel *Focus;
  int     Pos;
  //
  TMergeSplit() { Focus = NULL; Pos = 0;}
};

///////////////////////////////////////////////////////////////////////////////

struct TMouse
{
  bool                IsProcessed; 
  grf::TMouse::EState State;
  grf::TShift         Shift;
  grf::TPoint         PtClient;
  TPanel             *TopComponent;
  //
  TMouse() { IsProcessed = false; TopComponent = NULL;}
  //
  void operator = (const TMouse &V);

private:
  TGeometryRect GRect;
};

////////////////////////////////////////////////////////////////////////////////

struct TMouseWheel
{
  bool        IsProcessed; 
  int         Delta;
  grf::TPoint PtClient;
  grf::TShift Shift;
  //
  TMouseWheel() { IsProcessed = false; }
  //
  void operator = (const TMouseWheel &V);

private:
  TGeometryRect GRect;
};

///////////////////////////////////////////////////////////////////////////////

struct TPanelEvents : public TDebug
{
  /////////////////////////
  struct TBeforeKeyboardKey
  {
    grf::TKeyboardKey &KeyboardKey;
    //
    TBeforeKeyboardKey(
      grf::TKeyboardKey &keyboardKey
    )
    :KeyboardKey(keyboardKey) {
    }
  };
  struct TAfterKeyboardKey
  {
    grf::TKeyboardKey &KeyboardKey;
    //
    TAfterKeyboardKey(
      grf::TKeyboardKey &keyboardKey
    ) 
    :KeyboardKey(keyboardKey) {
    }
  };
  virtual void Event(TBeforeKeyboardKey &Param) {}
  virtual void Event(TAfterKeyboardKey  &Param) {}

  //////////////////////////
  struct TBeforeKeyboardChar
  {
    grf::TKeyboardChar &KeyboardChar;
    //
    TBeforeKeyboardChar(grf::TKeyboardChar &keyboardChar) : KeyboardChar(keyboardChar) {}
  };
  struct TAfterKeyboardChar
  {
    grf::TKeyboardChar &KeyboardChar;
    //
    TAfterKeyboardChar(grf::TKeyboardChar &keyboardChar) : KeyboardChar(keyboardChar) {}
  };
  virtual void Event(TBeforeKeyboardChar &Param) {}
  virtual void Event(TAfterKeyboardChar  &Param) {}

  ///////////////////
  struct TSelectEnter
  {
  };
  virtual void Event(TSelectEnter &Param) {}
};

///////////////////////////////////////////////////////////////////////////////

struct TPanel : public geometry::TRect
{
  struct TStyle : public frm::TStyle
  {
    svl_Type(frm::TStyle)
    cursor::TCursor Cursor;
    filler::TFiller Filler;
    TBorder         Border;
    //
    virtual void SetFromParent(frm::TStyle *Parent);
    virtual svl::TInfoParam AddInfoTo(svl::TInfoParam Info);
  };
  
/****************************  
  ////////////////////////////////////////////////////////
  struct TEventsList; struct TEvents : public svl::TEvents
  {
    ///////////////////////////////////////////
    struct TParam : public svl::TEvents::TParam
    {
      TPanel &Sender;
      //
      TParam(TEventsList &eventsList) : svl::TEvents::TParam(eventsList),Sender(eventsList.Sender) {}
    };

    //virtual void TEvents_BeforeChangeWidth(TI&I,TPanel &Sender,int OldVal,int &NewVal) { TEvents *P = (TEvents*)I.GetPrev(); if (P) { P->TEvents_BeforeChangeWidth(I,Sender,OldVal,NewVal);} }
    //virtual void TEvents_AfterChangeWidth (TI&I,TPanel &Sender,int OldVal,int  NewVal) { TEvents *P = (TEvents*)I.GetPrev(); if (P) { P->TEvents_AfterChangeWidth (I,Sender,OldVal,NewVal);} }
    
    ///////////////////////////////
    struct TEvMouse : public TParam
    {
      TMouse &Mouse;
      //
      TEvMouse(TEventsList &eventsList,TMouse &mouse) : TParam(eventsList),Mouse(mouse) {}
    };
    virtual void TEvents_Mouse(TEvMouse &Param) { TEvents *P = (TEvents*)Param.GetPrev(); if (P) { P->TEvents_Mouse(Param);} }

    ////////////////////////////////////
    struct TEvMouseWheel : public TParam
    {
      TMouseWheel &MouseWheel;
      //
      TEvMouseWheel(TEventsList &eventsList,TMouseWheel &mouseWheel) : TParam(eventsList),MouseWheel(mouseWheel) {}
    };
    virtual void TEvents_MouseWheel(TEvMouseWheel &Param) { TEvents *P = (TEvents*)Param.GetPrev(); if (P) { P->TEvents_MouseWheel(Param);} }

    //////////////////////////////////
    struct TFocusEnter : public TParam
    {
      TFocusEnter(TEventsList &eventsList) : TParam(eventsList) {}
    };
    virtual void TEvents_FocusEnter(TFocusEnter &Param) { TEvents *P = (TEvents*)Param.GetPrev(); if (P) { P->TEvents_FocusEnter(Param);} }

    /////////////////////////////////
    struct TFocusExit : public TParam
    {
      TFocusExit(TEventsList &eventsList) : TParam(eventsList) {}
    };
    virtual void TEvents_FocusExit(TFocusExit  &Param) { TEvents *P = (TEvents*)Param.GetPrev(); if (P) { P->TEvents_FocusExit(Param);} }
    
    /////////////////////////////////////
    struct TEvKeyboardKey : public TParam
    {
      grf::TKeyboardKey &KeyboardKey;
      //
      TEvKeyboardKey(TEventsList &eventsList,grf::TKeyboardKey &keyboardKey) : TParam(eventsList),KeyboardKey(keyboardKey) {}
    };
    virtual void TEvents_KeyboardKey(TEvKeyboardKey &Param) { TEvents *P = (TEvents*)Param.GetPrev(); if (P) { P->TEvents_KeyboardKey(Param);} }
    
    //////////////////////////////////////
    struct TEvKeyboardChar : public TParam
    {
      grf::TKeyboardChar &KeyboardChar;
      //
      TEvKeyboardChar(TEventsList &eventsList,grf::TKeyboardChar &keyboardChar) : TParam(eventsList),KeyboardChar(keyboardChar) {}
    };
    virtual void TEvents_KeyboardChar(TEvKeyboardChar &Param) { TEvents *P = (TEvents*)Param.GetPrev(); if (P) { P->TEvents_KeyboardChar(Param);} }
    
    /////////////////////////////////////
    struct TChangeVisible : public TParam
    {
      bool &Visible;
      //
      TChangeVisible(TEventsList &eventsList,bool &visible) : TParam(eventsList),Visible(visible) {}
    };
    virtual void TEvents_BeforeChangeVisible(TChangeVisible &Param) { TEvents *P = (TEvents*)Param.GetPrev(); if (P) { P->TEvents_BeforeChangeVisible(Param);} }
    virtual void TEvents_AfterChangeVisible (TChangeVisible &Param) { TEvents *P = (TEvents*)Param.GetPrev(); if (P) { P->TEvents_AfterChangeVisible (Param);} }
  };
  ////////////////////////////////////////////
  struct TEventsList : public svl::TEventsList
  {
    TPanel &Sender;
    //
    TEventsList(TPanel &sender) : Sender(sender),svl::TEventsList(Default()) {}
    //
    void Link  (TEvents &V) { svl::TEventsList::Link  (V);}
    void Unlink(TEvents &V) { svl::TEventsList::Unlink(V);}
    //
    TEvents &Get() { return (TEvents&)svl::TEventsList::GetBot();}
    
  private:
    static TEvents &Default() { static TEvents E; return E;}
  }
  Events;
*****************************************/



  //
  TPanel(TWindow &Window);
 ~TPanel() { destructor();}
  svl_Type(TComponent)
  //
  void destructor();
  //
  void SetPanelEvents(TPanelEvents &V) { panelEvents = &V;}
  //
  TWindow      &GetWindow() { return window; }
  TPanelFocus  &GetFocus();
  TPanelSelect *GetSelectThisOrParent();
  TPanelMouse  &GetMouse();
  
  // add,delete child ///////
  struct TTempDisableCalcSize
  {
    TTempDisableCalcSize(TPanel *P) : p(*P) { old = P->enCalcSize; P->enCalcSize = false; }
   ~TTempDisableCalcSize()                  { p.enCalcSize = old; }
  private:
    bool old; TPanel &p;
  };
  friend TTempDisableCalcSize;
  //
  virtual void AddChildFirst (TComponent *Add,bool EnDelete = true);
  virtual void AddChildLast  (TComponent *Add,bool EnDelete = true);
  virtual void AddChildBefore(TComponent *Add,TComponent *Curr,bool EnDelete = true);
  virtual void AddChildAfter (TComponent *Add,TComponent *Curr,bool EnDelete = true);
  //
  virtual void MoveChildrenTo(int ThisNFirstChild,int ThisNLastChild,int ToNBeforeChild,TComponent *ToParent);

  // select //////////////////
  virtual bool Select_Enter();
  virtual bool Select_Exit();
  //
  bool    Select_Enable()   { return TComponent_SelectEnable(); }
  TPanel *Select_GetEnter() { TPanelSelect *P = GetSelectThisOrParent(); return P ? P->GetEnter() : NULL; }
  bool    Select_IsEnter()  { return Select_GetEnter() == this; }
  
  // focus ////////////////////////////////////////////////////
  bool Focus_Enable()      { return TComponent_FocusEnable(); }
  int  Focus_GetX()        { return GetFocus().GetX(); }
  int  Focus_GetPos()      { return GetFocus().GetPos(); }
  void Focus_SetPos(int V) { GetFocus().SetPos(V); }
  void Focus_FixCaretX()   { GetFocus().FixCaretX(); }
  //
  virtual bool Focus_EnterByPos(int Pos) { return focus_SetEnterByPos(this,Pos); }
  virtual bool Focus_EnterByX  (int X)   { return focus_SetEnterByX(this,X); }
  virtual bool Focus_Enter()             { return focus_SetEnterByPos(this,0); }
  virtual void Focus_Exit()              { GetFocus().Exit(); }
  //
  bool    Focus_IsEnter()  { return GetFocus().GetEnter() == this; }
  TPanel *Focus_GetEnter() { return GetFocus().GetEnter(); }
  
  // mouse ///////////////////////////////////////////////////
  void Mouse_SetCapture()     { GetMouse().SetCapture(this); }
  void Mouse_ReleaseCapture() { GetMouse().SetCapture(NULL); }

  // style ///////////////////////////
  TStyle &GetStyle() { return *style;}
  TPanel &SetStyle(TStyle &V);
  void UpdateStyle(TStyle &V);

  // tableOfStyles /////////////////////////////////////////////
  void SetTableOfStyles(TTableOfStyles *P) { tableOfStyles = P;}
  TTableOfStyles *GetTableOfStyles() { return tableOfStyles;}

  // RuleSize ///////////////////////////////////////////////////////////////////////////////////////////
  TPanel &SetRuleWidth (geometry::TCalcSize *V,bool EnDelete = true) { GetGeometry().SetWidth (V,EnDelete); return *this;}
  TPanel &SetRuleHeight(geometry::TCalcSize *V,bool EnDelete = true) { GetGeometry().SetHeight(V,EnDelete); return *this;}
  // RuleAlign ///////////////////////////////////////////////////////////////////////////////////////////////
  TPanel &SetRuleWAlign(geometry::TAlignChildren *V,bool EnDelete = true) { GetGeometry().SetWAlign(V,EnDelete); return *this;}
  TPanel &SetRuleHAlign(geometry::TAlignChildren *V,bool EnDelete = true) { GetGeometry().SetHAlign(V,EnDelete); return *this;}
  // RuleDirect ///////////////////////////////////////////////////////////////////////////////////////////////
  TPanel &SetRuleDirect(geometry::TDirectChildren *V,bool EnDelete = true) { GetGeometry().SetDirect(V,EnDelete); return *this;}

  ///////////////////////////////////////////////////////////////////////////////////
  TPanel &Width(geometry::TCalcSize &V) { GetGeometry().SetWidth(V.New()); return *this;}
  TPanel &Width_Fixed(int Size = 0) { return Width(geometry::TFixed(Size));}
  TPanel &Width_ChildrenSum()       { return Width(geometry::TChildrenSum());}
  TPanel &Width_ChildrenMax()       { return Width(geometry::TChildrenMax());}
  TPanel &Width_ChildrenMaxBase()   { return Width(geometry::TChildrenMaxBase());}
  TPanel &Width_Parent()            { return Width(geometry::TParent());}
  TPanel &Width_SiblingsRem()       { return Width(geometry::TSiblingsRem());}
  TPanel &Width_SiblingsMax()       { return Width(geometry::TSiblingsMax());}
  //
  TPanel &Height(geometry::TCalcSize &V) { GetGeometry().SetHeight(V.New()); return *this;}
  TPanel &Height_Fixed(int Size = 0) { return Height(geometry::TFixed(Size));}
  TPanel &Height_ChildrenSum()       { return Height(geometry::TChildrenSum());}
  TPanel &Height_ChildrenMax()       { return Height(geometry::TChildrenMax());}
  TPanel &Height_ChildrenMaxBase()   { return Height(geometry::TChildrenMaxBase());}
  TPanel &Height_Parent()            { return Height(geometry::TParent());}
  TPanel &Height_SiblingsRem()       { return Height(geometry::TSiblingsRem());}
  TPanel &Height_SiblingsMax()       { return Height(geometry::TSiblingsMax());}
  //
  TPanel &DirectChildren(geometry::TDirectChildren &V) { GetGeometry().SetDirect(V.New()); return *this;}
  TPanel &DirectChildren_Vert()                        { return DirectChildren(geometry::TVert());}
  TPanel &DirectChildren_Horz()                        { return DirectChildren(geometry::THorz());}
  //
  TPanel &WAlignChildren(geometry::TAlignChildren &V) { GetGeometry().SetWAlign(V.New()); return *this;}
  TPanel &WAlignChildren_Begin()                      { return WAlignChildren(geometry::TBegin());}
  TPanel &WAlignChildren_BeginBase()                  { return WAlignChildren(geometry::TBeginBase());}
  TPanel &WAlignChildren_Center()                     { return WAlignChildren(geometry::TCenter());}
  TPanel &WAlignChildren_CenterBase()                 { return WAlignChildren(geometry::TCenterBase());}
  TPanel &WAlignChildren_End()                        { return WAlignChildren(geometry::TEnd());}
  TPanel &WAlignChildren_EndBase()                    { return WAlignChildren(geometry::TEndBase());}
  TPanel &WAlignChildren_Justify()                    { return WAlignChildren(geometry::TJustify());}
  //
  TPanel &HAlignChildren(geometry::TAlignChildren &V) { GetGeometry().SetHAlign(V.New()); return *this;}
  TPanel &HAlignChildren_Begin()                      { return HAlignChildren(geometry::TBegin());}
  TPanel &HAlignChildren_BeginBase()                  { return HAlignChildren(geometry::TBeginBase());}
  TPanel &HAlignChildren_Center()                     { return HAlignChildren(geometry::TCenter());}
  TPanel &HAlignChildren_CenterBase()                 { return HAlignChildren(geometry::TCenterBase());}
  TPanel &HAlignChildren_End()                        { return HAlignChildren(geometry::TEnd());}
  TPanel &HAlignChildren_EndBase()                    { return HAlignChildren(geometry::TEndBase());}
  TPanel &HAlignChildren_Justify()                    { return HAlignChildren(geometry::TJustify());}
  ///////////////////////////////////////////////////////////////////////////////////////////////////

  // paint /////////////////
  virtual void BeginPaint();
  virtual void InsertPaint(TRect *Rect);
  virtual void EndPaint();
  
  // visible ////////////////////////
  virtual void UpdateVisible(bool V);
  virtual bool IsVisibleInParents();
  
  // scroll ////////////////////////////
  void SetScrollChildren(grf::TPoint V);
  grf::TPoint GetScrollChildren();
  void UpdateScrollChildren(grf::TPoint V);
  void UpdateXScrollChildren(int X);
  void UpdateYScrollChildren(int Y);
  
  //
  virtual bool DeleteSymbolInPos(int Pos) { return false; }
  //
  bool SearchIndexChild(const svl::TType &TypeChild,TPanel *InChild,int &OutIndex);
  //
  TPanel *SearchChildByIndex(const svl::TType &TypeChild,int InIndex);
  TPanel *SearchNearestCommonParent(TPanel *Child1,TPanel *Child2);
  //
  int  CalcChildrenCountByType(svl::TType &TypeChild);
  void SearchChildrenByType   (svl::TType &TypeChild,TComponentArray &Result);
  //
  TPanel *SearchNextChild           (const svl::TType &TypeChild,TPanel *CurrChild = NULL,bool EnCheckVisibleInParents = true);
  TPanel *SearchNextChildFocusEnable(const svl::TType &TypeChild,TPanel *CurrChild = NULL);
  TPanel *SearchPrevChild           (const svl::TType &TypeChild,TPanel *CurrChild = NULL,bool EnCheckVisibleInParents = true);
  TPanel *SearchPrevChildFocusEnable(const svl::TType &TypeChild,TPanel *CurrChild = NULL);

//protected:
  virtual void TComponent_Paint(TPaint &Paint,int NPaintStack);
  //
  virtual bool TComponent_IsFormClient() { return false;}
//virtual bool TComponent_IsForm()       { return false;}

  void InheritStyle()
  {
    if (!tableOfStyles) {
      Except("InheritStyle[!tableOfStyles]");
    }
    TTableOfStyles TS; TS.ReplaceLinkFrom(*tableOfStyles);
    InheritStyleFrom(TS);
  }
  virtual void InheritStyleFrom(TTableOfStyles &ParentStyles);
  virtual void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);

  //
  virtual bool TComponent_TransparentForFocus() { return true;}
  virtual bool TComponent_FocusEnable() { return false;}
  virtual void TComponent_FocusEnter () {}// Events.Get().TEvents_FocusEnter(TEvents::TFocusEnter(Events)); }
  virtual void TComponent_FocusExit  () {}// Events.Get().TEvents_FocusExit (TEvents::TFocusExit (Events)); }
  //
  virtual TPanelSelect *TComponent_GetPanelSelect() { return NULL;}
  virtual bool TComponent_SelectEnable() { return false;}
  virtual void TComponent_SelectEnter () { panelEvents->Event( TPanelEvents::TSelectEnter() );}
  virtual void TComponent_SelectExit  () {}
  //
  virtual bool TComponent_CaretIsBegin() { return false;}
  virtual bool TComponent_CaretIsEnd  () { return false;}
  //
  virtual void TComponent_SetCaretToBegin() {}
  virtual void TComponent_SetCaretToEnd  () {}
  //
  virtual int TComponent_GetCaretMaxPos() { return 0;}
  //
  virtual void TComponent_SetCaretByX    (TGeometryRect &GRect,int XClient){}
  virtual void TComponent_SetCaretByPos  (TGeometryRect &GRect,int Pos){}
  virtual void TComponent_ScrollToVisible(TGeometryRect &GRect) {}
  //
  virtual void TComponent_KeyboardKey (grf::TKeyboardKey  &KeyboardKey);
  virtual void TComponent_KeyboardChar(grf::TKeyboardChar &KeyboardChar);
  //
  virtual void TComponent_Mouse(TMouse Mouse);
  virtual void TComponent_SetCursor();
  virtual void TComponent_MouseEnter() {}
  virtual void TComponent_MouseExit () {}
  virtual void TComponent_MouseWheel(TMouseWheel MouseWheel);
  //
  virtual TComponent *TComponent_SplitInSize(TMergeSplit &MS,int InSize) { return NULL;}
  virtual TComponent *TComponent_SplitInPos (TMergeSplit &MS,int InPos)  { return NULL;}
  virtual bool        TComponent_MergeFrom  (TMergeSplit &MS,TComponent *InCFrom) { return false;}
  //
  virtual void TComponent_BeforeUnlinkThis();
  virtual void TComponent_AfterUnlinkChildren();
  //
  virtual void TComponent_BeforeDeleteRow(TTable *Table) {}

/****************  
  //
  virtual void TComponent_BeforeUpdateWidth(int OldWidth,int &NewWidth) { Events.BeforeChangeWidth(OldWidth,NewWidth); }
  virtual void TComponent_AfterUpdateWidth (int OldWidth,int  NewWidth) { Events.AfterChangeWidth (OldWidth,NewWidth); }
  //
  virtual void TComponent_BeforeUpdateHeight(int OldHeight,int &NewHeight) {}
  virtual void TComponent_AfterUpdateHeight (int OldHeight,int  NewHeight) {}
****************/  
  
private:
  TPanel *getParent()     { return dynamic_cast<TPanel*>(GetParent()); }
  TPanel &getChild(int N) { return dynamic_cast<TPanel&>(GetChild(N)); }
  //
  bool focus_SetEnterByPos(TPanel *V,int Pos);
  bool focus_SetEnterByX  (TPanel *V,int X);
  //
  TPanel *searchNextChild           (svl::TType &TypeChild,TPanel *CurrChild,bool EnCheckVisibleInParents,bool Start);
  TPanel *searchNextChildFocusEnable(svl::TType &TypeChild,TPanel *CurrChild,bool Start);
  TPanel *searchPrevChild           (svl::TType &TypeChild,TPanel *CurrChild,bool EnCheckVisibleInParents,bool Start);
  TPanel *searchPrevChildFocusEnable(svl::TType &TypeChild,TPanel *CurrChild,bool Start);
  //
  bool    searchIndexChild  (svl::TType &TypeChild,TPanel *InChild,int &OutIndex,bool Start);
  TPanel *searchChildByIndex(svl::TType &TypeChild,int InIndex,bool Start);
  //
  TPanelEvents &defaultPanelEvents() {
    static TPanelEvents Events; 
    return Events;
  }
  TPanelEvents *panelEvents;
  //
  TWindow &window;
  TStyle *style;
  TTableOfStyles *tableOfStyles;
  bool enCalcSize;
  friend TPanelFocus;
  friend TPanelSelect;
  friend TPanelMouse;
  friend TWindow;
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////

struct TPanelDeletor : public svl::TPointer
{
  void Add(TPanel *Parent,int NChild) {
    TPanel *PChild = dynamic_cast<TPanel*>(
      &Parent->GetChild(NChild)
    );
    
    if (Parent->GetEnDeleteChild(NChild)) {
      Parent->SetEnDeleteChild(NChild,false);
      PChild->destructor();
      a.AddLast(PChild);
    }
    Parent->DeleteChild(NChild);
  }
  void Add(TPanel *Parent,TPanel *PChild) {
    Add(Parent,Parent->GetNChild(PChild));
  }
  void Delete() {
    for (int N = a.Count()-1; N >= 0; N--) {
      delete a.Get(N);
    }
    a.Clear();
  }
  //
 ~TPanelDeletor() {
    Delete();
  }

private:  
  svl::TArrayPtrFix<TPanel*,1000> a;
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////

struct TWindowClient : public TPanel
{
  struct TStyle : public TPanel::TStyle
  {
    svl_Type(TPanel::TStyle)
  };
  //
  TWindowClient(TWindow &Window);
  //
  virtual bool TComponent_IsFormClient() { return true;}
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
  { 
    TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
      SetStyle(*Style);
    } 
    else {
      //TPanel::TComponent_InheritStyleFrom(ParentStyles);
    }
  }
};

///////////////////////////////////////////////////////////////////////////////

struct TWindow : public grf::TWindow
{
  ////////////////////////////////////////////////////////
  struct TEventsList; struct TEvents : public svl::TEvents
  {
    ///////////////////////////////////////////
    struct TParam : public svl::TEvents::TParam
    {
      TWindow &Sender;
      //
      TParam(TEventsList &eventsList) : svl::TEvents::TParam(eventsList),Sender(eventsList.Sender) {}
    };
    /////////////////////////////
    struct TClose : public TParam
    {
      bool &EnClose;
      //
      TClose(TEventsList &eventsList,bool &enClose) : TParam(eventsList),EnClose(enClose) {}
    };
    virtual void TEvents_BeforeClose(TClose &Param) { TEvents *P = (TEvents*)Param.GetPrev(); if (P) { P->TEvents_BeforeClose(Param);} }
  };
  ////////////////////////////////////////////
  struct TEventsList : public svl::TEventsList
  {
    TWindow &Sender;
    //
    TEventsList(TWindow &sender) : Sender(sender),svl::TEventsList(Default()) {}
    //
    void Link  (TEvents &V) { svl::TEventsList::Link  (V);}
    void Unlink(TEvents &V) { svl::TEventsList::Unlink(V);}
    //
    TEvents &Get() { return (TEvents&)svl::TEventsList::GetBot();}

  private:
    static TEvents &Default() { static TEvents E; return E;}
    friend TPanel;
  }
  Events;
  //
  TPanelPaint   PanelPaint;
  TPanelFocus   PanelFocus;
  TPanelMouse   PanelMouse;
  TPanelDeletor PanelDeletor;
  TWindowClient Client;
  //
  TWindow();
 ~TWindow();
  //
  bool CalcGeometryRect(TPanel *InComponent,TGeometryRect &OutRect);

protected:
  virtual void TWindow_ShowWindow(bool Show);
  virtual void TWindow_Paint(grf::TPaint &Paint);
  virtual void TWindow_Mouse(grf::TMouse &Mouse);
  virtual void TWindow_MouseWheel(grf::TMouseWheel &Param);
  virtual void TWindow_MouseExit() { PanelMouse.SetEnter(NULL);}
  //                                               
  virtual void TWindow_FocusEnter();
  virtual void TWindow_FocusExit ();
  //
  virtual void TWindow_Activate(bool Activate);
  //
  virtual void TWindow_KeyboardKey (grf::TKeyboardKey  &KeyboardKey);
  virtual void TWindow_KeyboardChar(grf::TKeyboardChar &KeyboardChar);
  //
  virtual void TWindow_AfterChangeClientSize(grf::TSize ClientSize);

protected:
  virtual LRESULT TWindow_WndProc(TMessage &Message);
};

///////////////////////////////////////////////////////////////////////////////
}}

#endif
